﻿using System;
using System.Runtime.InteropServices;
using DataMonitor.Logging;
using HPSocketCS;
namespace DataMonitor.Model
{
    public class TcpMonitor : MonitorBase
    {
        private TcpServer _server = new TcpServer();
        private readonly string _ip;
        private readonly ushort _port;
        public TcpMonitor(string ip, ushort port)
        {
            _ip = ip;
            _port = port;
            InitTcpServer();
        }
        ~TcpMonitor()
        {
            try
            {
                _server.Stop();
            }
            catch (Exception ex)
            {
                Log4NetAdapter.Instance.Write(ex);
            }
        }
        public override bool Send(byte[] buffer)
        {
            try
            {
                var ids = _server.GetAllConnectionIDs();
                if (ids != null && buffer.Length > 0)
                {
                    foreach (var id in ids)
                    {
                        _server.Send(id, buffer, buffer.Length);
                    }
                }
            }
            catch (Exception ex)
            {
                Log4NetAdapter.Instance.Write(ex);
                return false;
            }
            return true;
        }
        private void InitTcpServer()
        {
            try
            {
                // 设置回调函数
                _server.SetCallback(i => HandleResult.Ok,
                OnAccept, OnSend, OnReceive, OnClose, OnError, OnServerShutdown);
                // 启动服务
                if (_server.Start(_ip, _port))
                {
                    throw new Exception(string.Format("$Server Start OK -> ({0}:{1})", _ip, _port));
                }
                throw new Exception(string.Format("$Server Start Error -> {0}({1})", _server.GetLastErrorDesc(), _server.GetlastError()));
            }
            catch (Exception ex)
            {
                Log4NetAdapter.Instance.Write(ex);
            }
        }
        HandleResult OnAccept(IntPtr dwConnId, IntPtr pClient)
        {
            // 客户进入了
            // 获取客户端ip和端口
            string ip = string.Empty;
            ushort port = 0;
            if (_server.GetRemoteAddress(dwConnId, ref ip, ref port))
            {
                string message = string.Format(" > [{0},OnAccept] -> ({1}:{2})", dwConnId, ip, port);
                Log4NetAdapter.Instance.Write(message);
            }
            else
            {
                Log4NetAdapter.Instance.Write(string.Format(" > [{0},OnAccept] -> Server_GetClientAddress() Error", dwConnId));
            }
            return HandleResult.Ok;
        }
        HandleResult OnSend(IntPtr dwConnId, IntPtr pData, int iLength)
        {
            // 服务器发数据了
            Log4NetAdapter.Instance.Write(string.Format(" > [{0},OnSend] -> ({1} bytes)", dwConnId, iLength));
            return HandleResult.Ok;
        }
        HandleResult OnReceive(IntPtr dwConnId, IntPtr pData, int iLength)
        {
            // 数据到达了
            try
            {
                Log4NetAdapter.Instance.Write(string.Format(" > [{0},OnReceive] -> ({1} bytes)", dwConnId, iLength));
                byte[] bytes = new byte[iLength];
                Marshal.Copy(pData, bytes, 0, iLength);
                var msg = OnReceiveEvent(bytes);
                if (!string.IsNullOrEmpty(msg) && ShowMsgAction != null)
                {
                    ShowMsgAction(msg);
                }
                return HandleResult.Ok;
            }
            catch (Exception)
            {
                return HandleResult.Ignore;
            }
        }
        HandleResult OnClose(IntPtr dwConnId)
        {
            // 客户离开了
            // 释放附加数据
            if (_server.SetConnectionExtra(dwConnId, null) == false)
            {
                Log4NetAdapter.Instance.Write(string.Format(" > [{0},OnClose] -> SetConnectionExtra({0}, null) fail", dwConnId));
            }
            string ip = string.Empty;
            ushort port = 0;
            if (_server.GetRemoteAddress(dwConnId, ref ip, ref port))
            {
                string str = string.Format(" > [{0},OnClose] -> ({1}:{2})", dwConnId, ip, port); ;
                Log4NetAdapter.Instance.Write(str);
            }
            return HandleResult.Ok;
        }
        HandleResult OnError(IntPtr dwConnId, SocketOperation enOperation, int iErrorCode)
        {
            // 客户出错了
            Log4NetAdapter.Instance.Write(string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", dwConnId, enOperation, iErrorCode));
            return OnClose(dwConnId);
        }
        HandleResult OnServerShutdown()
        {
            // 服务关闭了
            Log4NetAdapter.Instance.Write(" > [OnServerShutdown]");
            return HandleResult.Ok;
        }
    }
}
